package is.api.demo.isgateway.utils;


import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 密钥转换工具类
 *
 * @author chen.chen
 */
public abstract class Sm2CertUtils {

    //SM2算法名
    public static final String ALGORITHM_NAME = "EC";

    //缓存
    private static final Map<String, String> CACHE = new ConcurrentHashMap<>();

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private Sm2CertUtils() {
    }

    /**
     * 证书密钥转换(私钥)
     *
     * @param privateKey 证书私钥
     * @return 私钥
     */
    public static String getPrivateKeyStrFromPKCS8(final String privateKey) throws Exception {
        if (CACHE.containsKey(privateKey)) {
            return CACHE.get(privateKey);
        } else {
            final String key = Sm2KeyUtils.getPriHex(Sm2CertUtils.getPrivateKeyFromPKCS8(privateKey));
            CACHE.put(privateKey, key);
            return key;
        }
    }

    /**
     * 证书密钥转换(私钥)
     *
     * @param privateKey 证书私钥
     * @return 私钥
     */
    private static PrivateKey getPrivateKeyFromPKCS8(final String privateKey) throws Exception {
        //转2进制数组
        final ByteArrayInputStream ins = new ByteArrayInputStream(privateKey.getBytes());
        //2进制字节
        final byte[] privateKeyBytes = is.api.demo.isgateway.io.StreamUtil.readBytes(ins);
        //解码
        final byte[] privateKeyBase64EncodedByte = Base64.getDecoder().decode(privateKeyBytes);
        //获取 key 工厂
        final KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);
        //生成私钥
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBase64EncodedByte));
    }

    /**
     * 证书密钥转换(公钥)
     *
     * @param publicKey 证书公钥
     * @return 公钥
     */
    public static String getPublicKeyStrFromX509(final String publicKey) throws Exception {
        if (CACHE.containsKey(publicKey)) {
            return CACHE.get(publicKey);
        } else {
            synchronized (publicKey) {
                if (CACHE.containsKey(publicKey)) {
                    return CACHE.get(publicKey);
                }
                final String key = Sm2KeyUtils.getPubHex(getPublicKeyFromX509(publicKey));
                CACHE.put(publicKey, key);
                return key;
            }
        }
    }

    /**
     * 证书密钥转换(公钥)
     *
     * @param publicKey 证书公钥
     * @return 公钥
     */
    private static PublicKey getPublicKeyFromX509(final String publicKey) throws Exception {
        final ByteArrayInputStream ins = new ByteArrayInputStream(publicKey.getBytes());
        final StringWriter writer = new StringWriter();
        is.api.demo.isgateway.io.StreamUtil.copy(new InputStreamReader(ins), writer);
        final byte[] publicKeyBytes = writer.toString().getBytes();
        final byte[] encodedKey = Base64.getDecoder().decode(publicKeyBytes);
        final KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);
        return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    }
}
